package com.xiaoyudeguang.apt;

import com.baomidou.mybatisplus.annotation.TableName;
import com.google.auto.service.AutoService;
import com.xiaoyudeguang.annotations.AptIgnore;
import freemarker.template.TemplateException;
import org.apache.ibatis.annotations.Mapper;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author 赵光
 */
@AutoService(Processor.class)
@SupportedAnnotationTypes("com.baomidou.mybatisplus.annotation.TableName")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MapperProcessor extends AbstractProcessor {

    private Filer filer;
    private Messager messager;
    private Map<String, String> options;
    private MapperGenerator mapperGenerator;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        this.filer = processingEnv.getFiler();
        this.messager = processingEnv.getMessager();
        this.options = processingEnv.getOptions();
        this.mapperGenerator = new MapperGenerator(filer, messager, options);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        messager.printMessage(Diagnostic.Kind.WARNING, "开始生成");
        if (annotations.isEmpty()) {
            return false;
        }
        String mapperName = getMapperClassName("");
        Set<String> ignoreEntities = new HashSet<>();
        roundEnv.getElementsAnnotatedWith(AptIgnore.class).forEach(element -> {
            ignoreEntities.add(element.getSimpleName().toString());
        });
        roundEnv.getElementsAnnotatedWith(Mapper.class).forEach(element -> {
            ignoreEntities.add(element.getSimpleName().toString().replace(mapperName, ""));
        });
        // 扫描所有带有@TableName注解的类
        Set<? extends Element> entities = roundEnv.getElementsAnnotatedWith(TableName.class);
        for (Element element : entities) {
            if (element instanceof TypeElement) {
                try {
                    if (!ignoreEntities.contains(element.getSimpleName().toString())) {
                        generateMapper((TypeElement) element);
                    }
                } catch (Exception e) {
                    messager.printMessage(Diagnostic.Kind.ERROR, "生成Mapper接口失败: " + e.getMessage(), element);
                }
            }
        }
        return true;
    }

    private void generateMapper(TypeElement entityElement) throws TemplateException, IOException {
        // 解析实体类信息
        EntityInfo entityInfo = parseEntityInfo(entityElement);
        // 生成Mapper接口
        mapperGenerator.generate(entityInfo);
        messager.printMessage(Diagnostic.Kind.NOTE, "成功生成Mapper接口: " + entityInfo.getMapperClassName());
    }

    private EntityInfo parseEntityInfo(TypeElement entityElement) {
        EntityInfo info = new EntityInfo();

        // 获取实体类名和包名
        String fullClassName = entityElement.getQualifiedName().toString();
        String packageName = fullClassName.substring(0, fullClassName.lastIndexOf("."));
        String simpleClassName = entityElement.getSimpleName().toString();

        // 获取@TableName注解值
        TableName tableNameAnnotation = entityElement.getAnnotation(TableName.class);

        TypeMirror superClass = entityElement.getSuperclass();
        System.out.println(superClass);


        String tableName = tableNameAnnotation.value();

        // 构建Mapper类信息
        String mapperPackage = getMapperPackage(packageName);
        String mapperClassName = getMapperClassName(simpleClassName);

        info.setEntityPackage(packageName);
        info.setEntityClassName(simpleClassName);
        info.setEntityFullClassName(fullClassName);
        info.setTableName(tableName);
        info.setMapperPackage(mapperPackage);
        info.setMapperClassName(mapperClassName);
        info.setMapperFullClassName(mapperPackage + "." + mapperClassName);
        info.setSuperClassName(getSuperClassName(getSuperClassFullName()));
        info.setSuperClassFullName(getSuperClassFullName());
        return info;
    }

    private String getMapperPackage(String entityPackage) {
        // 从配置中获取Mapper包名，默认在entity包的上一级的mapper包下
        String mapperPackage = options.getOrDefault("mapper.package", "");
        if (!mapperPackage.isEmpty()) {
            return mapperPackage;
        }

        int lastDotIndex = entityPackage.lastIndexOf(".");
        if (lastDotIndex > 0) {
            return entityPackage.substring(0, lastDotIndex) + ".mapper";
        }
        return "mapper";
    }

    private String getMapperClassName(String entityName) {
        // 从配置中获取命名规则，默认是实体名+Mapper
        String namingPattern = options.getOrDefault("mapper.naming", "%sMapper");
        return String.format(namingPattern, entityName);
    }

    private String getSuperClassFullName() {
        // 从配置中获取命名规则，默认是实体名+Mapper
        return options.getOrDefault("interface.superClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper");
    }

    private String getSuperClassName(String superFullClassName) {
        return superFullClassName.substring(superFullClassName.lastIndexOf(".") + 1);
        // 从配置中获取命名规则，默认是实体名+Mapper

    }
}    